﻿using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.IdentityModel.Tokens;
using Abp.Runtime.Security;
using Microsoft.AspNetCore.Builder;
using Newtonsoft.Json;
using IdentityModel;
using IdentityServer4.Stores;
using System.Reflection;
using Avis.OutBoundAPI.Authentication.JwtBearer;
using IdentityServer4;
using IdentityServer4.Models;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Authorization.Infrastructure;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Internal;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;
using CryptoRandom = IdentityModel.CryptoRandom;

namespace Avis.OutBoundAPI.Web.Host.Startup
{
    ///// <inheritdoc />
    //public class AvisAuthorizationHandler : IAuthorizationHandler
    //{
    //    public Task HandleAsync(AuthorizationHandlerContext context)
    //    {
    //        var subjectRequirement = context.Requirements.FirstOrDefault(x =>
    //            (x as ClaimsAuthorizationRequirement)?.ClaimType == JwtClaimTypes.Subject);
    //        if (context.User.Claims.Any(x => x.Type == JwtClaimTypes.Subject))
    //        {
    //            context.Succeed(subjectRequirement);
    //            return Task.CompletedTask;
    //        }
    //        return Task.CompletedTask;
    //    }
    //}

    public static class AuthConfigurer
    {
        public static void Configure(IServiceCollection services, IConfiguration configuration)
        {
            services.AddAuthorization(options =>
            {
                //含sub才可访问
                options.AddPolicy("force_hybrid", builder =>
                {
                    builder.RequireAuthenticatedUser()
                        .RequireAssertion(context => context.User.Claims.Any(x => x.Type == JwtClaimTypes.Subject));
                });
            });

            //services.AddAuthorizationPolicyEvaluator();

            services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
                .AddIdentityServerAuthentication(options =>
                {
                    // base-address of your identityserver
                    options.Authority = configuration["Authentication:Authority"];
                    options.RequireHttpsMetadata = false;
                    // name of the API resource
                    options.ApiName = configuration["Authentication:ApiName"];
                    options.ApiSecret = configuration["Authentication:ApiSecret"];
                    //options.SaveToken = true;
                    //options.EnableCaching = true;
                });
        }

        /* This method is needed to authorize SignalR javascript client.
         * SignalR can not send authorization header. So, we are getting it from query string as an encrypted text. */
            private static Task QueryStringTokenResolver(MessageReceivedContext context)
        {
            if (!context.HttpContext.Request.Path.HasValue ||
                !context.HttpContext.Request.Path.Value.StartsWith("/signalr"))
            {
                // We are just looking for signalr clients
                return Task.CompletedTask;
            }

            var qsAuthToken = context.HttpContext.Request.Query["enc_auth_token"].FirstOrDefault();
            if (qsAuthToken == null)
            {
                // Cookie value does not matches to querystring value
                return Task.CompletedTask;
            }

            // Set auth token from cookie
            context.Token = SimpleStringCipher.Instance.Decrypt(qsAuthToken, AppConsts.DefaultPassPhrase);
            return Task.CompletedTask;
        }
    }
}
